import {
  world,
  EquipmentSlot,
  Player,
  ItemStack,
  GameMode,
  BlockStates,
  Entity,
} from "@minecraft/server";
import { axeConvertBlockIds, shovelConvertBlockIds, utils } from "../..";

/**
 * Define a tool tag.
 */
export class ToolTag {
  constructor(
    /**
     * The weapon tag.
     */
    public tag: string,
    public options?: ToolOptions
  ) {
    this.listeningDurability();
    if (this.options?.type === ToolType.SHOVEL)
      this.listeningShovelDurability();
    if (this.options?.type === ToolType.AXE) this.listeningAxeDurability();
  }
  /**
   * Automatically consume durability for the tools.
   */
  listeningDurability() {
    world.afterEvents.playerBreakBlock.subscribe((event) => {
      const [PLAYER, ITEM] = [
        event.player,
        utils.getEquipmentItem(event.player),
      ];
      if (
        PLAYER.getGameMode() === GameMode.survival ||
        PLAYER.getGameMode() === GameMode.adventure
      ) {
        if (ITEM?.hasTag(this.tag)) {
          const NEW_ITEM = utils.consumeDurability(ITEM, 1, PLAYER);
          PLAYER?.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          if (NEW_ITEM === undefined) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
    world.afterEvents.entityHitEntity.subscribe((event) => {
      const [ENTITY, ITEM] = [
        event.damagingEntity,
        utils.getEquipmentItem(event.damagingEntity),
      ];
      if (ENTITY instanceof Player) {
        if (
          ENTITY.getGameMode() === GameMode.survival ||
          ENTITY.getGameMode() === GameMode.adventure
        ) {
          if (ITEM?.hasTag(this.tag)) {
            const NEW_ITEM = utils.consumeDurability(ITEM, 2, ENTITY);
            ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
              EquipmentSlot.Mainhand,
              NEW_ITEM
            );
          }
        }
      } else if (ITEM?.hasTag(this.tag)) {
        const NEW_ITEM = utils.consumeDurability(
          ITEM,
          2,
          ENTITY instanceof Player ? ENTITY : undefined
        );
        ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
          EquipmentSlot.Mainhand,
          NEW_ITEM
        );
        if (NEW_ITEM === undefined) {
          this.options?.destroyedAfterEvents(ENTITY);
        }
      }
    });
  }
  /**
   * Consume durability when the tool use on dirts.
   */
  listeningShovelDurability() {
    world.afterEvents.itemUseOn.subscribe((event) => {
      const [ITEM, BLOCK, PLAYER] = [
        event.itemStack,
        event.block,
        event.source,
      ];
      if (ITEM.hasTag(this.tag)) {
        /**
         * 锹压地的事件
         */
        if (shovelConvertBlockIds.includes(BLOCK.typeId)) {
          const NEW_ITEM = utils.consumeDurability(ITEM, 1, PLAYER);
          PLAYER.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          PLAYER.playSound("step.grass");
          if (NEW_ITEM === undefined) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
  }
  /**
   * Consume durability when the tool use on logs.
   */
  listeningAxeDurability() {
    world.afterEvents.itemUseOn.subscribe((event) => {
      const [ITEM, BLOCK, PLAYER] = [
        event.itemStack,
        event.block,
        event.source,
      ];
      if (ITEM.hasTag(this.tag)) {
        const NEW_ITEM = utils.consumeDurability(ITEM, 1, PLAYER);
        /**
         * 斧剥皮的事件
         */
        if (axeConvertBlockIds.includes(BLOCK.typeId)) {
          PLAYER.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          PLAYER.playSound("use.wood");
          if (NEW_ITEM === undefined) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
  }
}

/**
 * Define a tool.
 */
export class ToolItem {
  constructor(
    /**
     * Item of the weapon.
     */
    public item: ItemStack,
    /**
     * Type of the tool.
     */
    public options?: ToolOptions
  ) {
    this.listeningDurability();
    if (this.options?.type === ToolType.SHOVEL)
      this.listeningShovelDurability();
    if (this.options?.type === ToolType.AXE) this.listeningAxeDurability();
  }
  /**
   * Automatically consume durability for the tools.
   */
  listeningDurability() {
    world.afterEvents.playerBreakBlock.subscribe((event) => {
      const [PLAYER, ITEM] = [
        event.player,
        utils.getEquipmentItem(event.player),
      ];
      if (
        PLAYER.getGameMode() === GameMode.survival ||
        PLAYER.getGameMode() === GameMode.adventure
      ) {
        if (ITEM?.typeId === this.item.typeId) {
          const NEW_ITEM = utils.consumeDurability(ITEM, 1, PLAYER);
          PLAYER?.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          if (NEW_ITEM === undefined) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
    world.afterEvents.entityHitEntity.subscribe((event) => {
      const [ENTITY, ITEM] = [
        event.damagingEntity,
        utils.getEquipmentItem(event.damagingEntity),
      ];
      if (ENTITY instanceof Player) {
        if (
          ENTITY.getGameMode() === GameMode.survival ||
          ENTITY.getGameMode() === GameMode.adventure
        ) {
          if (ITEM?.typeId === this.item.typeId) {
            const NEW_ITEM = utils.consumeDurability(ITEM, 1, ENTITY);
            ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
              EquipmentSlot.Mainhand,
              NEW_ITEM
            );
            if (NEW_ITEM === undefined) {
              this.options?.destroyedAfterEvents(ENTITY);
            }
          }
        }
      } else if (ITEM?.typeId === this.item.typeId) {
        const NEW_ITEM = utils.consumeDurability(ITEM, 1, ENTITY);
        ENTITY?.getComponent("minecraft:equippable")?.setEquipment(
          EquipmentSlot.Mainhand,
          NEW_ITEM
        );
        if (NEW_ITEM === undefined) {
          this.options?.destroyedAfterEvents(ENTITY);
        }
      }
    });
  }
  /**
   * Consume durability when the tool use on dirts.
   */
  listeningShovelDurability() {
    world.afterEvents.itemUseOn.subscribe((event) => {
      const [ITEM, BLOCK, PLAYER] = [
        event.itemStack,
        event.block,
        event.source,
      ];
      if (ITEM.typeId === this.item.typeId) {
        /**
         * 锹压地的事件
         */
        if (shovelConvertBlockIds.includes(BLOCK.typeId)) {
          const NEW_ITEM = utils.consumeDurability(ITEM, 1, PLAYER);
          PLAYER.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          PLAYER.playSound("step.grass");
          if (NEW_ITEM === undefined) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
  }
  /**
   * Consume durability when the tool use on logs.
   */
  listeningAxeDurability() {
    world.afterEvents.itemUseOn.subscribe((event) => {
      const [ITEM, BLOCK, PLAYER] = [
        event.itemStack,
        event.block,
        event.source,
      ];
      if (ITEM.typeId === this.item.typeId) {
        /**
         * 斧剥皮的事件
         */
        if (axeConvertBlockIds.includes(BLOCK.typeId)) {
          const NEW_ITEM = utils.consumeDurability(ITEM, 1, PLAYER);
          PLAYER.getComponent("minecraft:equippable")?.setEquipment(
            EquipmentSlot.Mainhand,
            NEW_ITEM
          );
          PLAYER.playSound("use.wood");
          if (NEW_ITEM === undefined) {
            this.options?.destroyedAfterEvents(PLAYER);
          }
        }
      }
    });
  }
}

/**
 * Type of the tool.
 */
export enum ToolType {
  AXE,
  SHOVEL,
  HOE,
  PICKAXE,
  CUSTOM,
}

export interface ToolOptions {
  /**
   * Type of the tool.
   */
  type?: ToolType;
  /**
   * @beta
   */
  destroyedAfterEvents: (holder: Entity) => void;
}
